/*
    SEL - Simple DirectMedia Layer Extension Library
    Copyright (C) 2001 Matej Knopp <knopp@users.sf.net>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef __sel_thread_h__
#define __sel_thread_h__

#include "sdl.h"

/*
 * Okay, perhaps having this class is not a very good idea.
 * Should I remove it?
 */

namespace SEL
{

//! Thread manipulation class.
/*!
  Thread is process, but unlike standard processes, threads can share common
  memory. This makes communication between threads easier, but also more
  dangerous. To protect variables that are being accessed from multiple 
  threads, you should use SEL::Mutex.
  \sa SEL::Mutex, SEL::Semaphore, SEL::Cond
 */
class Thread
{
public:
	//! Create a new thread.
	/*!
	  On any error throws an exception.
	  \param fn function that will be executed as a new thread.
	  \param data data passed to the function
	 */
	Thread (int (*fn)(void*), void* data = NULL);
	
	//! Destroy a thread.
	~Thread ();
	
	//! Get the 32 bit thread identifier.
	Uint32 id () const;
	
	//! Wait for a thread to finish.
	/*!
	  The return code for the thread function is stored in \a status.
	  \param status reference to a variable where the return value
	  of the thread will be stored.
	  \param delete_self whether to delete the thread instance after
	  the thread finishes.
         */
	void wait (int &status, bool delete_self = true);
	
	//! Wait for a thread to finish.
	/*!
	  \param delete_self whether to delete the thread instance after
	  the thread finishes.
         */
	void wait (bool delete_self = true);
	
	//! Forcefully kill the thread without worrying about its state.
	/*!
	  \param delete_self whether to delete the thread instance after
	  the thread's killed.
	 */
	void kill (bool delete_self = true);
	
	//! Get the 32 bit identifier for current thread.
	static Uint32 currentID ();
	
	//! Get the wrapped SDL::Thread structure.
	SDL::Thread *thread () 			{ return m_thread; }

	//! Get the wrapped constant SDL::Thread structure.
	const SDL::Thread *thread () const		{ return m_thread; }

protected:
	//! The wrapped SDL::Thread structure.
	SDL::Thread *m_thread;
};

//////////////////////////////////////////////////////////////////
//////////////////////// INLINE FUNCTIONS ////////////////////////
//////////////////////////////////////////////////////////////////

inline 
Thread::~Thread ()
{
	if (m_thread)
		SDL::KillThread (m_thread);
}
	
inline Uint32 
Thread::id () const
{
	return SDL::GetThreadID (m_thread);
}
	
inline Uint32 
Thread::currentID ()
{
	return SDL::ThreadID ();
}
	
}; // namespace SEL

#endif // __sel_thread_h__
